package com.tools.common.object.type.handler;

import com.fasterxml.jackson.core.JsonParser;
import com.tools.common.container.*;
import com.tools.common.container.r.OnlyReadArrayList;
import com.tools.common.exception.ParseRuntimeException;
import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.type.CTKit;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * List 集合的类型处理器
 * */
@Note("List 集合的类型处理器")
public final class ListTypeHandler {

    private ListTypeHandler() {}

    /* ************************************************************************************************************
     *
     *          转换的功能方法
     *
     * ************************************************************************************************************
     * */

    @Note("将 source 转换为 List 集合")
    public static List castToList(Object source, C<?> targetType) {
        Class<?> mainType = targetType.getMainType();
        if(ArrayList.class.equals(mainType) || Collection.class.equals(mainType) || List.class.equals(mainType)) {
            return arrayList(source, targetType);
        }
        if(LinkedList.class.equals(mainType)) {
            return linkedList(source, targetType);
        }
        if(OnlyReadArrayList.class.equals(mainType)) {
            return onlyReadArrayList(source, targetType);
        }
        if(CopyOnWriteArrayList.class.equals(mainType)) {
            return copyOnWriteArrayList(source, targetType);
        }
        if(AbstractList.class.equals(mainType) || AbstractCollection.class.equals(mainType)) {
            return arrayList(source, targetType);
        }
        return otherList(source, targetType);
    }



    @Note("使用 JsonParser 流模式将 JSON 转为 List 集合")
    public static List castToList(JsonParser parser, C<?> targetType) {
        Class<?> mainType = targetType.getMainType();
        try {
            if(ArrayList.class.equals(mainType) || Collection.class.equals(mainType) || List.class.equals(mainType)) {
                ArrayList list = arrayList(targetType);
                return (List) CTKit.addJsonDataInCollection(parser, list, targetType);
            }
            if(LinkedList.class.equals(mainType)) {
                LinkedList list = linkedList(targetType);
                return (List) CTKit.addJsonDataInCollection(parser, list, targetType);
            }
            if(OnlyReadArrayList.class.equals(mainType)) {
                ArrayList list = onlyReadTempArrayList(targetType);
                CTKit.addJsonDataInCollection(parser, list, targetType);
                return new OnlyReadArrayList(list);
            }
            if(CopyOnWriteArrayList.class.equals(mainType)) {
                ArrayList list = copyOnWriteArrayListTempArrayList(targetType);
                CTKit.addJsonDataInCollection(parser, list, targetType);
                return new CopyOnWriteArrayList(list);
            }
            if(AbstractList.class.equals(mainType) || AbstractCollection.class.equals(mainType)) {
                ArrayList list = arrayList(targetType);
                return (List) CTKit.addJsonDataInCollection(parser, list, targetType);
            }
            List list = (List) ObjKit.buildObject(targetType);
            return (List) CTKit.addJsonDataInCollection(parser, list, targetType);
        } catch (Exception e) {
            throw new ParseRuntimeException(e);
        }
    }

    @Note("将 source 转换为 AbsOwnList 集合")
    public static AbsOwnList castToAbsOwnList(Object source, C<?> targetType) {
        Class<?> mainType = targetType.getMainType();
        if(OwnList.class.equals(mainType) || OwnRows.class.equals(mainType) || AbsOwnList.class.equals(mainType)) {
            return ownList(source, targetType);
        }
        return otherOwnList(source, targetType);
    }


    @Note("使用 JsonParser 流模式将 JSON 转为 AbsOwnList 集合")
    public static AbsOwnList castToAbsOwnList(JsonParser parser, C<?> targetType) {
        Class<?> mainType = targetType.getMainType();
        try {
            if(OwnList.class.equals(mainType) || OwnRows.class.equals(mainType) || AbsOwnList.class.equals(mainType)) {
                OwnList list = ownList(targetType);
                return (AbsOwnList) CTKit.addJsonDataInOwnRows(parser, list, targetType);
            }
            AbsOwnList list = (AbsOwnList) ObjKit.buildObject(targetType);
            return (AbsOwnList) CTKit.addJsonDataInOwnRows(parser, list, targetType);
        } catch (Exception e) {
            throw new ParseRuntimeException(e);
        }
    }


    /* ************************************************************************************************************
     *
     *          构建空集合的方法
     *
     * ************************************************************************************************************
     * */

    @Note("构建空的 ArrayList 集合")
    public static ArrayList arrayList(C<?> targetType) {
        Object first = targetType.getArgValue(0);
        if(first instanceof Integer) {
            return new ArrayList((Integer) first);
        }
        if(first instanceof Collection) {
            return new ArrayList((Collection) first);
        }
        return new ArrayList();
    }


    @Note("构建空的 LinkedList 集合")
    public static LinkedList linkedList(C<?> targetType) {
        Object first = targetType.getArgValue(0);
        if(first instanceof Collection) {
            return new LinkedList((Collection) first);
        }
        return new LinkedList();
    }

    @Note("构建空的临时的 ArrayList，用于后续生成 CopyOnWriteArrayList 集合")
    public static ArrayList copyOnWriteArrayListTempArrayList(C<?> targetType) {
        Object first = targetType.getArgValue(0);
        if(first instanceof Collection) {
            return new ArrayList((Collection) first);
        }
        return private_newArrayListByOrArray(first);
    }


    @Note("获取空的临时的 ArrayList，用于后续生成只读 ArrayList -> OnlyReadArrayList")
    public static ArrayList onlyReadTempArrayList(C<?> targetType) {
        Object first = targetType.getArgValue(0);
        if(first instanceof Iterable) {
            Iterable f = (Iterable) first;
            ArrayList temp = new ArrayList(RowKit.getIterableSize(f));
            CTKit.iterableToCollection(f, temp);
            return temp;
        }
        return private_newArrayListByOrArray(first);
    }


    @Note("构建空的 OwnList 集合")
    public static OwnList ownList(C<?> targetType) {
        Object first = targetType.getArgValue(0);
        if(first == null) return new OwnList();
        if(first instanceof Integer) {
            return new OwnList((Integer) first);
        }
        if(first.getClass().isArray()) {
            return new OwnList((Object[]) first);
        }
        if(first instanceof Iterable) {
            Iterable f = (Iterable) first;
            Object second = targetType.getArgValue(1);
            if(second instanceof Comparator) {
                return new OwnList(f, (Comparator) second);
            }
            return new OwnList(f);
        }
        if(first instanceof Comparator) {
            Comparator f = (Comparator) first;
            Object second = targetType.getArgValue(1);
            if(second != null && second.getClass().isArray()) {
                return new OwnList(f, (Object[]) second);
            }
            return new OwnList(f);
        }
        if(first instanceof ListEnum) {
            ListEnum f = (ListEnum) first;
            Object second = targetType.getArgValue(1);
            if(second == null) return new OwnList(f);
            if(second instanceof Integer) {
                return new OwnList(f, (Integer) second);
            }
            if(second.getClass().isArray()) {
                return new OwnList(f, (Object[]) second);
            }
            if(second instanceof Comparator) {
                Object third = targetType.getArgValue(2);
                return new OwnList(f, (Comparator) second, (Object[]) third);
            }
            if(second instanceof Iterable) {
                Iterable s = (Iterable) second;
                Object third = targetType.getArgValue(2);
                if(third instanceof Comparator) {
                    return new OwnList(f, s, (Comparator) third);
                }
                return new OwnList(f, s);
            }
        }
        return new OwnList();
    }


    /* ************************************************************************************************************
     *
     *          构建完整数据集合的功能方法
     *
     * ************************************************************************************************************
     * */

    @Note("ArrayList 集合的类型转换")
    public static ArrayList arrayList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            ArrayList list = arrayList(targetType);
            CTKit.iterableToCollectionFillIn((Iterable) source, list, targetType);
            return list;
        }
        if(sourceClass.isArray()) {
            ArrayList list = arrayList(targetType);
            CTKit.arrayToCollectionFillIn((Object[]) source, list, targetType);
            return list;
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 java.util.ArrayList");
    }


    @Note("LinkedList 集合的类型转换")
    public static LinkedList linkedList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            LinkedList list = linkedList(targetType);
            CTKit.iterableToCollectionFillIn((Iterable) source, list, targetType);
            return list;
        }
        if(sourceClass.isArray()) {
            LinkedList list = linkedList(targetType);
            CTKit.arrayToCollectionFillIn((Object[]) source, list, targetType);
            return list;
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 java.util.LinkedList");
    }


    @Note("CopyOnWriteArrayList 集合的类型转换")
    public static CopyOnWriteArrayList copyOnWriteArrayList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            ArrayList temp = copyOnWriteArrayListTempArrayList(targetType);
            CTKit.iterableToCollectionFillIn((Iterable) source, temp, targetType);
            return new CopyOnWriteArrayList(temp);
        }
        if(sourceClass.isArray()) {
            ArrayList temp = copyOnWriteArrayListTempArrayList(targetType);
            CTKit.arrayToCollectionFillIn((Object[]) source, temp, targetType);
            return new CopyOnWriteArrayList(temp);
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 java.util.concurrent.CopyOnWriteArrayList");
    }


    @Note("只读的 ArrayList -> OnlyReadArrayList 集合的类型转换")
    public static OnlyReadArrayList onlyReadArrayList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            ArrayList temp = onlyReadTempArrayList(targetType);
            CTKit.iterableToCollectionFillIn((Iterable) source, temp, targetType);
            return new OnlyReadArrayList(temp);
        }
        if(sourceClass.isArray()) {
            ArrayList temp = onlyReadTempArrayList(targetType);
            CTKit.arrayToCollectionFillIn((Object[]) source, temp, targetType);
            return new OnlyReadArrayList(temp);
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 com.tools.common.container.r.OnlyReadArrayList");
    }






    @Note("生成其他未知类型的 List 集合")
    public static List otherList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            List list = (List) ObjKit.buildObject(targetType);
            CTKit.iterableToCollectionFillIn((Iterable) source, list, targetType);
            return list;
        }
        if(sourceClass.isArray()) {
            List list = (List) ObjKit.buildObject(targetType);
            CTKit.arrayToCollectionFillIn((Object[]) source, list, targetType);
            return list;
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 " + targetType.getMainType().getName());
    }


    @Note("OwnList 集合的类型转换")
    public static OwnList ownList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            OwnList list = ownList(targetType);
            CTKit.iterableToOwnRowsFillIn((Iterable) source, list, targetType);
            return list;
        }
        if(sourceClass.isArray()) {
            OwnList list = ownList(targetType);
            CTKit.arrayToOwnRowsFillIn((Object[]) source, list, targetType);
            return list;
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 com.tools.common.container.OwnList");
    }

    @Note("生成其他未知类型的 AbsOwnList 集合")
    public static AbsOwnList otherOwnList(Object source, C<?> targetType) {
        Class<?> sourceClass = source.getClass();
        if(Iterable.class.isAssignableFrom(sourceClass)) {
            AbsOwnList list = (AbsOwnList) ObjKit.buildObject(targetType);
            CTKit.iterableToOwnRowsFillIn((Iterable) source, list, targetType);
            return list;
        }
        if(sourceClass.isArray()) {
            AbsOwnList list = (AbsOwnList) ObjKit.buildObject(targetType);
            CTKit.arrayToOwnRowsFillIn((Object[]) source, list, targetType);
            return list;
        }
        throw new ClassCastException("无法将 " + sourceClass.getName() +
                " 的 【" + source + "】 转为 com.tools.common.container.AbsOwnList");
    }

    /* ************************************************************************************************************
     *
     *          私有逻辑
     *
     * ************************************************************************************************************
     * */

    @Note("抽取公共部分，判断参数是否是数组，不是的话那就构建空 ArrayList")
    private static ArrayList private_newArrayListByOrArray(Object first) {
        if(first != null && first.getClass().isArray()) {
            Object[] f = (Object[]) first;
            ArrayList temp = new ArrayList(f.length);
            Collections.addAll(temp, f);
            return temp;
        }
        return new ArrayList();
    }




}
